package com.yeskery.nut.cloud.feign;

import com.yeskery.nut.core.HttpHeader;
import com.yeskery.nut.core.MediaType;
import com.yeskery.nut.core.NameAndValue;
import com.yeskery.nut.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;

/**
 * feign请求处理类
 * @author YESKERY
 * 2024/1/19
 */
public interface FeignRequestHandler {

    /**
     * 执行feign请求
     * @param feignRequestMetadata feign请求元数据
     * @param feignRequestData feign请求数据
     * @return 执行后的返回结果
     */
    Object handle(FeignRequestMetadata feignRequestMetadata, FeignRequestData feignRequestData);

    /**
     * 添加feign请求拦截器
     * @param feignRequestInterceptor feign请求拦截器
     */
    void addInterceptor(FeignRequestInterceptor feignRequestInterceptor);

    /**
     * 获取远程请求url
     * @param feignRequestMetadata feign请求元数据
     * @param feignRequestData 获取feign请求数据
     * @return 远程请求url
     */
    default String getOriginalRequestUrl(FeignRequestMetadata feignRequestMetadata, FeignRequestData feignRequestData) {
        StringBuilder url = new StringBuilder(feignRequestData.getUrl());
        boolean hasBody = !StringUtils.isEmpty(feignRequestData.getBodyString()) || feignRequestData.getBodyResource() != null;
        if (feignRequestMetadata.getMethod() == com.yeskery.nut.core.Method.GET
                || (hasBody && !feignRequestData.getParams().isEmpty())) {
            List<NameAndValue> nameAndValues = feignRequestData.getParams();
            for (int i = 0; i < nameAndValues.size(); i++) {
                NameAndValue nameAndValue = nameAndValues.get(i);
                String value;
                try {
                    value = URLEncoder.encode(nameAndValue.getValue(), StandardCharsets.UTF_8.name());
                } catch (UnsupportedEncodingException e) {
                    value = nameAndValue.getValue();
                }
                url.append(i == 0 ? "?" : "&").append(nameAndValue.getKey()).append("=").append(value);
            }
        }
        return url.toString();
    }

    /**
     * 获取远程请求体
     * @param feignRequestData 获取feign请求数据
     * @return 远程请求体
     */
    default String getOriginalRequestBodyString(FeignRequestData feignRequestData) {
        if (StringUtils.isEmpty(feignRequestData.getBodyString())) {
            return feignRequestData.getParams().stream().map(e -> {
                try {
                    return e.getKey() + "=" + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8.name());
                } catch (UnsupportedEncodingException ex) {
                    return e.getKey() + "=" + e.getValue();
                }
            }).collect(Collectors.joining("&"));
        }
        return feignRequestData.getBodyString();
    }

    /**
     * 获取远程请求媒体类型
     * @param feignRequestData 获取feign请求数据
     * @return 远程请求媒体类型
     */
    default MediaType getOriginalRequestMediaType(FeignRequestData feignRequestData) {
        if (feignRequestData.getHeaders().stream().anyMatch(e -> HttpHeader.CONTENT_TYPE.equals(e.getKey()))) {
            return null;
        }
        if (feignRequestData.getBodyResource() != null) {
            return MediaType.APPLICATION_OCTET_STREAM;
        }
        return StringUtils.isEmpty(feignRequestData.getBodyString()) ? MediaType.APPLICATION_X_WWW_FORM_URLENCODED : MediaType.APPLICATION_JSON;
    }
}
